﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Windows.Forms;
using Newtonsoft.Json.Linq;
using XFControls.Utils;
using XFControls.XFPanels;
using XFControls.XFPanels.XFPanelItems;
using XFItemControls.XFPanels.XFPanelItems;
using XFControls;
using FBEntities.FBObjects;

namespace XDAFacebook
{
    public partial class ImageViewer : Form
    {
        private XFItemLoading _loading;
        public string ImageUri;

        private FBPhoto _photo;
        private WebDownloaderWrapper _albumWrapper;
        private JArray _album;
        private int _curIndex;

        public ImageViewer(FBPhoto photo)
            : this(photo.images.First().source)
        {
            _photo = photo;
            LoadAlbum();
        }

        public ImageViewer(string uri)
        {
            InitializeComponent();

            ImageUri = uri;
            var imagePanel = GetImagePanel(uri);

            xfPanelContainer.SetMainPanel(imagePanel);
        }

        private XFPanelImage GetImagePanel(string uri)
        {
            var imagePanel = new XFPanelImage
                             {
                                 LoadingString = Settings.LocalizationStrings.Loading + "\n\n" + uri
                             };

            if (File.Exists(uri))
                imagePanel.SetImage(uri);
            else if (Uri.IsWellFormedUriString(uri, UriKind.RelativeOrAbsolute))
            {
                var worker = new XFWorkerGeneric();
                worker.Work += DownloadImage;

                _loading = new XFItemLoading(worker) { Parent = imagePanel };
                _loading.DoWork();
            }

            imagePanel.PreviousImageClick += (o, e) => PreviousImage();
            imagePanel.NextImageClick += (o, e) => NextImage();
            imagePanel.CommentsClick += (o, e) => LoadComments();
            imagePanel.ExitClick += (o, e) => Close();
            return imagePanel;
        }

        private void LoadCommentCount()
        {
            string url = "https://graph." + Settings.Domain + ".com/" + _album[_curIndex]["object_id"] + "?" + FBParseUtilities.authKey;
            var wrapper = new WebDownloaderWrapper(url);
            wrapper.GetResults += (o, e) =>
                                      {
                                          var photo = new FBPhoto();
                                          photo.Parse(JObject.Parse(e.Text));

                                          if (photo.comments != null)
                                          {
                                              int count = photo.comments.data == null
                                                              ? photo.comments.count
                                                              : photo.comments.data.Count;
                                              ((XFPanelImage)xfPanelContainer.MainPanel).CommentCount = count;
                                          }
                                      };
            wrapper.BeginDownload();
        }

        private void LoadAlbum()
        {
            if (_photo == null) return;

            _albumWrapper = XFItemControlUtils.GetFQL("SELECT object_id, src_big FROM photo WHERE aid IN (SELECT aid FROM photo WHERE object_id = \"" + _photo.id + "\")");
            _albumWrapper.GetResults += AlbumWrapperGetResults;
            _albumWrapper.BeginDownload();
        }

        void AlbumWrapperGetResults(object sender, TextEventArgs e)
        {
            _album = JArray.Parse(e.Text);
            for (int i = 0; i < _album.Count; i++)
            {
                if (_photo.id != _album[i]["object_id"].ToString()) continue;
                _curIndex = i;
                break;
            }
            LoadCommentCount();
        }

        void LoadComments()
        {
            DialogResult = DialogResult.Yes;
            Close();
        }

        void PreviousImage()
        {
            //  SELECT object_id FROM album WHERE aid IN (SELECT aid FROM photo WHERE object_id = "810265205049")
            //  SELECT object_id, src_big FROM photo WHERE aid IN (SELECT aid FROM photo WHERE object_id = "810265205049")

            if (_album == null || _albumWrapper == null || _curIndex == 0 || _albumWrapper.IsDownloading) return;
            _curIndex--;

            ImageUri = _album[_curIndex]["src_big"].ToString().Trim('\"');
            var prev = GetImagePanel(ImageUri);
            xfPanelContainer.MainPanel.SetLeftPanel(prev);
            xfPanelContainer.MainPanel.EnableSlide();
            LoadCommentCount();
        }

        void NextImage()
        {
            if (_album == null || _albumWrapper == null || _curIndex >= _album.Count - 1 || _albumWrapper.IsDownloading) return;
            _curIndex++;

            ImageUri = _album[_curIndex]["src_big"].ToString().Trim('\"');
            var next = GetImagePanel(ImageUri);
            xfPanelContainer.MainPanel.SetRightPanel(next);
            xfPanelContainer.MainPanel.EnableSlide();
            LoadCommentCount();
        }

        void DownloadImage(object sender, EventArgs e)
        {
            try
            {
                if (XFGraphics.ImageCache.ContainsKey(ImageUri))
                {
                    if (File.Exists(XFGraphics.ImageCache[ImageUri]))
                    {
                        ((XFPanelImage)xfPanelContainer.MainPanel).SetImage(XFGraphics.ImageCache[ImageUri]);
                    }
                }
            }
            catch (KeyNotFoundException) { }

            var buffer = DownloadImageFile(ImageUri);

            for (int i = 0; i < 4 && buffer == null; i++)
                buffer = DownloadImageFile(ImageUri);

            if (buffer != null)
            {
                XFGraphics.CacheImage(ImageUri, buffer);

                ((XFPanelImage)xfPanelContainer.MainPanel).SetImage(XFGraphics.ImageCache[ImageUri], buffer);
            }
            if (_loading != null)
                _loading.Dispose();
            _loading = null;
        }

        private static byte[] DownloadImageFile(string url)
        {
            try
            {
                var uri = new Uri(url);

                var webRequest = (HttpWebRequest)WebRequest.Create(uri);
                webRequest.Method = "GET";
                webRequest.Headers.Add("Accept-Encoding", "gzip, deflate");
                webRequest.Timeout = WebDownloader.LoginTimeOut;
                webRequest.ProtocolVersion = new Version(1, 1);
                webRequest.KeepAlive = false;
                webRequest.AllowAutoRedirect = true;
                if (WebDownloader.useEmptyProxy)
                {
                    webRequest.Proxy = GlobalProxySelection.GetEmptyWebProxy();
                }

                using (var webResponse = (HttpWebResponse)webRequest.GetResponse())
                {
                    if (webResponse.StatusCode.ToString().Equals("OK"))
                    {
                        using (Stream responseStream = AsyncWebDownloader.DeflateStream(webResponse))
                        {
                            if (responseStream == null)
                                return null;

                            using (var ms = new MemoryStream())
                            {
                                XFGraphics.CopyStream(responseStream, ms);
                                ms.Position = 0;
                                var ret = new byte[ms.Length];
                                ms.Read(ret, 0, ret.Length);
                                return ret;
                            }
                        }
                    }
                }
            }
            catch (WebException e)
            {
                string error = "";
                if (e.Response != null)
                    using (var response = e.Response)
                    using (var resp = response.GetResponseStream())
                    using (var errorStream = new StreamReader(resp))
                        error = errorStream.ReadToEnd();
            }
            catch (Exception exp)
            {
            }

            return null;
        }

        private void ImageViewer_Closed(object sender, EventArgs e)
        {
            if (_albumWrapper != null)
                _albumWrapper.Dispose();
        }
    }
}